package com.userautentification.dao.imp;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.userautentification.dao.DataAccessLayerException;
import com.userautentification.dao.GenericDao;
import com.userautentification.dao.HibernateFactory;
import com.userautentification.entities.Role;

/**
 * This class serves as the Base class for all other DAOs - namely to hold
 * common CRUD methods that they might all use. You should only need to extend
 * this class when your require custom CRUD logic.
 * <p/>
 * <p>
 * To register this class in your Spring context file, use the following XML.
 * 
 * <pre>
 *      &lt;bean id="fooDao" class="org.appfuse.dao.hibernate.GenericDaoHibernate"&gt;
 *          &lt;constructor-arg value="org.appfuse.model.Foo"/&gt;
 *      &lt;/bean&gt;
 * </pre>
 * 
 * @author <a href="mailto:bwnoll@gmail.com">Bryan Noll</a>
 * @param <T>
 *            a type variable
 * @param <ID>
 *            the primary key for that type
 */
public abstract class GenericDaoHibernate<T, ID extends Serializable>
		implements GenericDao<T, ID> {


	 Log log = LogFactory.getLog(RoleDaoImp.class);
	    private Session session;
	    private Transaction tx;
	 /**
     * Insert a new Event into the database.
     * @param object
     */
    public void create(T object) throws DataAccessLayerException {
        log.info("create() method is called");
        try {
            startOperation();
            session.save(object);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }


    /**
     * Delete a detached Event from the database.
     * @param object
     */
    public void delete(T object) throws DataAccessLayerException {
        log.info("delete() method is called");
        try {
            startOperation();
            session.delete(object);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }
    /**
     * Find an Event by its primary key.
     * @param id
     * @return
     */
 /*   public T find(ID id) throws DataAccessLayerException {
        log.info("find() method is called");
        T object = null;
        try {
            startOperation();
            object = (T) session.load(T.class, id);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            //HibernateFactory.close(session);
        }
        return object;
    }
*/
    
    protected Object find(Class clazz, Long id) {
        Object obj = null;
        try {
            startOperation();
            obj = session.load(clazz, id);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
//            HibernateFactory.close(session);
        }
        return obj;
    }
    /**
     * Updates the state of a detached Event.
     *
     * @param object
     */
    public void update(T object) throws DataAccessLayerException {
        log.info("update() method is called");
        try {
            startOperation();
            session.update(object);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }

    /**
     * Finds all Events in the database.
     * @return
     */
/*    public List findAll() throws DataAccessLayerException{
        log.info("findAll() method is called");
        List objects = null;
        try {
            startOperation();
            Query query = session.createQuery("from Event");
            objects =  query.list();
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return objects;
    }*/

    protected List findAll(Class clazz) {
        List objects = null;
        try {
            startOperation();
            Query query = session.createQuery("from " + clazz.getName());
            objects = query.list();
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return objects;
    }
    private void handleException(HibernateException e) throws DataAccessLayerException {
        log.debug("Exception has occurred");
        HibernateFactory.rollback(tx);
        throw new DataAccessLayerException(e);
    }

    private void startOperation() throws HibernateException {
        session = HibernateFactory.openSession();
        tx = session.beginTransaction();
    }

}
